package com.sirap.spring.boot.demo.config;

import java.io.File;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.sirap.basic.thirdparty.ServletHelper;
import com.sirap.basic.tool.C;
import com.sirap.basic.tool.D;
import com.sirap.basic.util.Amaps;
import com.sirap.basic.util.DateUtil;
import com.sirap.basic.util.EmptyUtil;
import com.sirap.basic.util.FileUtil;
import com.sirap.basic.util.HttpUtil;
import com.sirap.basic.util.IOUtil;
import com.sirap.basic.util.RandomUtil;
import com.sirap.basic.util.StrUtil;
import com.sirap.basic.util.WebReader;
import com.sirap.basic.util.XXXUtil;

public class RingUtil {
	public static final String KEY_BALL = "ball";
	public static final String KEY_TITLE = "title";
	public static final String FORMAT_CONCISE = "yyMMdd_HHmmss";
	public static final String VIEW_URL = "/file/view/";
	
	public static String createFileViewUrl(HttpServletRequest request, String filename) {
		String template = "{0}/file/view/{1}";
		String homeUrl = ServletHelper.getHomeUrl(request);
		String va = StrUtil.occupy(template, homeUrl, filename);
		
		return va;
	}
	
	public static void saveFileFromMultipartRequest(MultipartHttpServletRequest mrequest, String storage, List<Map> infos) {
		try {
			Collection<List<MultipartFile>> coll  = mrequest.getMultiFileMap().values();
			for(List<MultipartFile> list : coll) {
				for(MultipartFile mfile : list) {
					String origin = mfile.getOriginalFilename();
					if(EmptyUtil.isNullOrEmpty(origin)) {
						D.pl("Empty file");
						continue;
					}
					D.pl("before " + origin);
					String legal = FileUtil.filenameWithExtensionOf(origin);
					String inshort = FileUtil.generateUrlFriendlyFilename(legal);
					D.pl("after " + inshort);
					D.pl("Uploading " + inshort + " " + FileUtil.formatSize(mfile.getSize()));
					try {
						Map info = Maps.newConcurrentMap();
						String finalname = DateUtil.strOf(new Date(), FORMAT_CONCISE) + "_" + inshort;
						String localpath = StrUtil.useSeparator(storage, finalname);
						String viewurl = createFileViewUrl(mrequest, finalname);
						IOUtil.save(mfile.getBytes(), localpath);
						info.put("name", inshort);
						info.put("finalname", finalname);
						info.put("viewurl", viewurl);
						info.put("localpath", localpath);
						infos.add(info);
						D.pl("Uploaded " + localpath);
					} catch(Exception ex) {
						String msg = StrUtil.occupy("上传文件{0}出现异常：{1}", inshort, ex.getMessage());
						infos.add(Amaps.createMap("error", msg));
		    			ex.printStackTrace();
					}
				}
			}
		} catch (Exception ex) {
			infos.add(Amaps.createMap("error", "上传文件操作出现异常：" + ex.getMessage()));
			ex.printStackTrace();
		}
	}
	
	public static void saveFiles(MultipartHttpServletRequest mrequest, String storage) {
		try {
			Collection<List<MultipartFile>> coll  = mrequest.getMultiFileMap().values();
			for(List<MultipartFile> list : coll) {
				for(MultipartFile mfile : list) {
					String origin = mfile.getOriginalFilename();
					if(EmptyUtil.isNullOrEmpty(origin)) {
						D.pl("Empty file");
						continue;
					}
//					D.pl("before " + origin);
					String legal = FileUtil.filenameWithExtensionOf(origin);
					String inshort = FileUtil.generateUrlFriendlyFilename(legal);
//					D.pl("after " + inshort);
					D.pla(origin, legal, inshort);
					D.pl("Uploading " + inshort + " " + FileUtil.formatSize(mfile.getSize()));
					String localpath = StrUtil.useSeparator(storage, inshort);
					if(!FileUtil.exists(localpath)) {
						IOUtil.save(mfile.getBytes(), localpath);
						D.pl("Uploaded " + localpath);
					} else {
						D.pl("Already exists: " + localpath);
					}
				}
			}
		} catch (Exception ex) {
			XXXUtil.alert(ex);
		}
	}
	
	public static Map<String, String> downloadIfPossible(String urlstring, String storage) {
		Map<String, List<String>> headers = WebReader.headersOf(urlstring);
		
		String appType = WebReader.applicationTypeOf(headers);
		if(appType != null) {
			String filename;
			String attachmentFilename = WebReader.attachmentFilenameOf(headers);
			if(attachmentFilename != null) {
				filename = attachmentFilename;
			} else {
				filename = HttpUtil.filenameByUrl(urlstring);
			}
			return downloadFile(urlstring, storage, filename);
		} else {
			String imageType = WebReader.imageTypeOf(headers);
			if(imageType != null) {
				String extension;
				String extensionFromUrl = HttpUtil.extensionOfUrl(urlstring);
				if(StrUtil.isIn(extensionFromUrl, FileUtil.EXTENSIONS_IMAGE)) {
					extension = extensionFromUrl;
				} else if(StrUtil.isIn(imageType, FileUtil.EXTENSIONS_IMAGE)) {
					extension = imageType;
				} else {
					extension = "png";
				}
				String tempFilename = HttpUtil.filenameByUrl(urlstring);
				String filename = tempFilename.replaceAll("\\..+", "") + "." + extension;
				return downloadFile(urlstring, storage, filename);
			}
		}
		
		return null;
	}
	
	private static Map<String, String> downloadFile(String url, String storage, String solidName) {
		String httpUrl = url;
		String jack = null;
		if(solidName != null) {
			jack = solidName;
		} else {
			jack = HttpUtil.filenameByUrl(url);
		}
		if(EmptyUtil.isNullOrEmpty(jack)) {
			jack = RandomUtil.letters(7);
		}
		
		String ts = DateUtil.strOf(new Date(), FORMAT_CONCISE);
		String finalname = StrUtil.occupy("{0}_{1}", ts, solidName);
		String localpath = StrUtil.useSeparator(storage, finalname);
		
		if(FileUtil.exists(localpath)) {
			C.pl("Existed => " + localpath);
		} else {
			FileUtil.makeDirectories(storage);
			C.pl("Fetching... " + httpUrl);
			boolean flag = IOUtil.downloadNormalFile(httpUrl, localpath, false);
			if(flag) {
				Map<String, String> info = Maps.newConcurrentMap();
				info.put("name", solidName);
				info.put("finalname", finalname);
				info.put("localpath", localpath);

				C.pl2("Saved => " + localpath);
				return info;
			}
		}
		
		return null;
	}

	public static void saveTextFromRequest(HttpServletRequest request, String storage, List<Map> infos) {
		try {
			String[] texts = request.getParameterValues(KEY_BALL);
			if(EmptyUtil.isNullOrEmpty(texts)) {
				return;
			}
			
//			D.pl(HttpUtil.detail(request));
			String title = request.getParameter(KEY_TITLE);
			List<String> list = Lists.newArrayList();
			for(String item : texts) {
				if(EmptyUtil.isNullOrEmptyOrBlank(item)) {
					continue;
				}
				String returnnewline = "\r\n";
				String[] lines = item.trim().split(returnnewline);
				for(String line : lines) {
					if(HttpUtil.isHttp(line)) {
						String urlstring = line;
						Map<String, String> info = downloadIfPossible(urlstring, storage);
						if(!EmptyUtil.isNullOrEmpty(info)) {
							String viewurl = createFileViewUrl(request, info.get("finalname"));
							info.put("viewurl", viewurl);
							infos.add(info);
						}
						String anchor = "<a style=\"{1}\" href=\"{0}\">{0}</a>";
						list.add(StrUtil.occupy(anchor, urlstring, "text-decoration:underline"));
					} else {
						list.add(line);
					}
				}
			}
			
			D.list(list);
			
			if(list.isEmpty()) {
				return;
			}
			
			String origin;
			if(!EmptyUtil.isNullOrEmpty(title)) {
				origin = title.trim();
			} else {
				origin = RandomUtil.name();
			}
			
			String ts = DateUtil.strOf(new Date(), FORMAT_CONCISE);
			String finalname = StrUtil.occupy("{0}_{1}.txt", ts, origin);
			String localpath = StrUtil.useSeparator(storage, finalname);
			IOUtil.saveAsTxt(list, localpath);
			
			Map<String, String> info = Maps.newConcurrentMap();
			String viewurl = createFileViewUrl(request, finalname);
			info.put("name", origin);
			info.put("finalname", finalname);
			info.put("viewurl", viewurl);
			info.put("localpath", localpath);
			infos.add(info);
			D.pl("Saved " + localpath);
		} catch (Exception ex) {
			infos.add(Amaps.createMap("error", "上传文本操作出现异常：" + ex.getMessage()));
			ex.printStackTrace();
		}
	}
	
	public static Map deleteFile(String filename, String storage) {
		Map info = Maps.newConcurrentMap();
		
		String filepath = StrUtil.useSeparator(storage, filename);
		File file = FileUtil.getIfNormalFile(filepath);
		if(file == null) {
			info.put("error", "文件不存在：" + filename);
		} else {
			boolean flag = file.delete();
			if(flag) {
				info.put("info", "已成功删除文件：" + filename);
			} else {
				info.put("error", "未能删除文件：" + filename);
			}
		}

		return info;
	}
}
